package com.mashuai.utils.toolkit.core.msHttp;

import cn.hutool.http.ContentType;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.mashuai.utils.base.MsAssertUtils;
import com.mashuai.utils.toolkit.achieve.MsExegesis;
import org.apache.commons.collections.MapUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;

/**
 * @author mashuai
 * @ClassName: HttpUtils
 * @Description: 常用的发送http请求工具累
 */
@MsExegesis("常用的发送http请求工具累")
public class MsHttpUtils {
    private static final String JSON_HEADER_FORMAT = "application/json;charset=UTF-8";

    private static final String FORM_HEADER_FORMAT = "application/x-www-form-urlencoded";

    //默认接口3s超时
    private static int overtime = 3000;

    /**
     * 发送get请求。url?p1=&p2=
     *
     * @param url
     * @param pramsMap 携带的参数
     * @return
     * @author mashuai
     */

    @MsExegesis("发送get请求。url?p1=&p2=")
    public static String sendGet(String url, Map<String, Object> pramsMap) {
        String body = HttpUtil.get(url, pramsMap);
        return body;
    }

    /**
     * 发送get+自定义请求头数据。url?p1=&p2=
     * header：{"type":"","auth":""}
     *
     * @param url
     * @param pramsMap  携带的参数
     * @param headerMap 请求头
     * @return
     * @author mashuai
     */
    @MsExegesis("发送get+自定义请求头数据，url?p1=&p2。headerMap@{请求头信息}")
    public static String sendGetHeader(String url, Map<String, Object> pramsMap, Map<String, String> headerMap) {
        return HttpUtil.createGet(url).addHeaders(headerMap).form(pramsMap).timeout(overtime).execute().body();
    }

    /**
     * 发送post请求，鞋带字符串。* url?p1=&p2=
     *
     * @param url
     * @param params
     * @return
     * @author mashuai
     */
    @MsExegesis("发送post请求，鞋带字符串。* url?p1=&p2=")
    public static String sendPost(String url, String params) {
        return HttpRequest.post(url).body(params).timeout(overtime).execute().body();
    }

    /**
     * 发送参数为JSON的POST请求，用于大部分情况
     * url
     * body:{}
     *
     * @param url
     * @param dates
     * @return
     * @author mashuai
     */
    @MsExegesis("发送参数为JSON的POST请求，用于大部分情况。dates@携带任意json格式")
    public static String sendPostJSON(String url, Object dates) {
        String body = HttpRequest.post(url).header(Header.CONTENT_TYPE, JSON_HEADER_FORMAT)
                .body(JSONObject.toJSONString(dates))
                .timeout(overtime)
                .execute().body();
        return body;
    }

    /**
     * post请求，携带表单数据
     *
     * @param url
     * @param dates
     * @return
     * @author mashuai
     */
    @MsExegesis("post请求，携带表单数据")
    public static String sendPostForm(String url, Map<String, Object> dates) {
        String body = HttpRequest.post(url).header(Header.CONTENT_TYPE, FORM_HEADER_FORMAT).form(dates).timeout(overtime).execute().body();
        return body;
    }

    /**
     * 发送自定义的Header的,参数为JSON的POST请求(使用场景：一般请求头带有token，cookies等等。。。)
     *
     * @param url
     * @param dates
     * @param headerMap
     * @return
     * @author mashuai
     */
    @MsExegesis("发送自定义的Header的,参数为JSON的POST请求(使用场景：一般请求头带有token，cookies等等。。。)")
    public static String sendPostJsonHeader(String url, Object dates, Map<String, String> headerMap) {
        if (!headerMap.isEmpty()) {
            HttpRequest request = HttpRequest.post(url).header(Header.CONTENT_TYPE, JSON_HEADER_FORMAT);
            headerMap.forEach((t1, t2) -> request.header(t1, t2));
            String body = request.body(JSONObject.toJSONString(dates)).timeout(overtime).execute().body();
            return body;
        }
        return "headerMap参数不可为空！";
    }


    /**
     * 发送携带BasicAuth参数的pots请求
     *
     * @param url
     * @param dates
     * @param userName
     * @param passWord
     * @return
     * @author mashuai
     */
    @MsExegesis("发送携带BasicAuth参数的pots请求")
    public static String sendPostJsonBasicAuth(String url, Object dates, String userName, String passWord) {
        MsAssertUtils.objIsNulls(userName, passWord);
        HttpRequest request = HttpRequest.post(url).header(Header.CONTENT_TYPE, JSON_HEADER_FORMAT);
        request.basicAuth(userName, passWord);
        String body = request.body(JSONObject.toJSONString(dates)).timeout(overtime).execute().body();
        return body;
    }

    /**
     * 发送自定义的Header的,参数为JSON的POST请求(使用场景：一般请求头带有token，cookies等等。。。)
     *
     * @param url
     * @param requestMap 数据
     * @param headerMap  拼接的header
     * @return java.lang.String
     * @author mashuai
     */
    @MsExegesis("发送自定义的Header的,参数为JSON的POST请求(使用场景：一般请求头带有token，cookies等等。。。)")
    public static String sendPostFormHeader(String url, Map<String, Object> requestMap, Map<String, String> headerMap) {
        if (!headerMap.isEmpty()) {
            HttpRequest request = HttpRequest.post(url).header(Header.CONTENT_TYPE, FORM_HEADER_FORMAT);
            headerMap.forEach((t1, t2) -> request.header(t1, t2));
            String body = request.form(requestMap).timeout(overtime).execute().body();
            return body;
        }
        return "headerMap参数不可为空！";
    }

    /**
     * 携带文件流的POST请求，并且其他参数为JSON
     *
     * @param url
     * @param dates          json格式的数据
     * @param multipartFiles 文件流集合
     * @return
     * @author mashuai
     */
    @MsExegesis("携带文件流的POST请求，并且其他参数为JSON")
    public static String sendPostJsonFiles(String url, Object dates, MultipartFile[] multipartFiles) {
        String body = HttpRequest.post(url).header(Header.CONTENT_TYPE, JSON_HEADER_FORMAT)
                .body(JSONObject.toJSONString(dates))
                .form("files", multipartFiles)
                .timeout(overtime)
                .execute().body();
        return body;
    }

    /**
     * 以form表单提交文件流，并且携带参数
     *
     * @param url
     * @param dates
     * @param multipartFiles
     * @return
     * @author mashuai
     */
    @MsExegesis(" 以form表单提交文件流，并且携带参数")
    public static String sendPostFormFile(String url, Map<String, Object> dates, MultipartFile multipartFiles) {
        String id = MapUtils.getString(dates, "id");
        String imageType = MapUtils.getString(dates, "imageType");
        File[] f = new File[1];
        f[0] = convert(multipartFiles);
        String body = HttpRequest.post(url + "?id=" + id + "&imageType=" + imageType).header("Content-Type", ContentType.MULTIPART.toString())
                .form("static/template", f)
                .timeout(overtime)
                .execute().body();
        return body;
    }

    private static File convert(MultipartFile file) {
        Path newFile = Paths.get(file.getOriginalFilename());
        try (InputStream is = file.getInputStream();
             OutputStream os = Files.newOutputStream(newFile)) {
            byte[] buffer = new byte[4096];
            int read;
            while ((read = is.read(buffer)) > 0) {
                os.write(buffer, 0, read);
            }
        } catch (IOException e) {
            throw new RuntimeException("文件上传失败，请联系管理员");
        }
        return newFile.toFile();
    }

}
